package com.dqx.opengl_es_demo.face;

import android.content.Context;
import android.graphics.Rect;
import android.hardware.Camera;
import android.opengl.GLES20;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

import java.util.List;

import zeusees.tracking.Face;
import zeusees.tracking.FaceTracking;

public class FaceDetectionSurfaceView extends SurfaceView implements SurfaceHolder.Callback, Camera.PreviewCallback {
    //脸部追踪的工具类
    private FaceTracking mMultiTrack106;
    //FaceTracking是否已初始化
    private boolean mTrack106;
    //摄像头工具类
    private CameraUtils camera;
    //图形渲染的工具类
    private EGLUtils egl;
    //绘制追踪点的工具类
    private GLPoints points;
    //绘制摄像头画面的工具类
    private GLFrame frame;
    //饱和度
    public float s = 1;
    //色调
    public float h = 0;
    //亮度
    public float l = 0;

    public FaceDetectionSurfaceView(Context context) {
        this(context, null);
    }

    public FaceDetectionSurfaceView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public FaceDetectionSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        //初始化
        mMultiTrack106 = new FaceTracking(context);
        camera = new CameraUtils(context);
        frame = new GLFrame(context);
        points = new GLPoints(context);
        //设置监听回调
        camera.setPreviewCallback(this);
        getHolder().addCallback(this);
    }

    /**
     * 画布被创建的回调
     *
     * @param holder
     */
    @Override
    public void surfaceCreated(SurfaceHolder holder) {

    }

    /**
     * 画布发生变化的回调
     *
     * @param holder
     * @param format
     * @param width
     * @param height
     */
    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        //设置窗口的绘制区域
        GLES20.glViewport(0, 0, CameraUtils.PREVIEW_WIDTH, CameraUtils.PREVIEW_HEIGHT);

        if (egl == null) {
            egl = new EGLUtils();
            egl.initEGL(holder.getSurface());
        }
        points.init();
        frame.init(width, height);
        camera.openCamera(frame.getSurfaceTexture());
    }

    /**
     * 画布被销毁的回调
     *
     * @param holder
     */
    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        camera.release();
        frame.release();
        points.release();
        egl.release();
    }

    /**
     * 摄像头实时捕获画面的回调
     *
     * @param data
     * @param c
     */
    @Override
    public void onPreviewFrame(byte[] data, Camera c) {
        //清除深度缓冲与颜色缓冲
        GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);

        //设置饱和度
        frame.setS(s);
        //设置色调
        frame.setH(h);
        //亮度
        frame.setL(l);
        //绘制摄像头捕获到的画面
        frame.drawFram();

        if (!mTrack106) {
            //初始化脸部追踪工具类
            mMultiTrack106.FaceTrackingInit(data, CameraUtils.PREVIEW_HEIGHT, CameraUtils.PREVIEW_WIDTH);
            mTrack106 = !mTrack106;
        } else {
            //更新数据
            mMultiTrack106.Update(data, CameraUtils.PREVIEW_HEIGHT, CameraUtils.PREVIEW_WIDTH);
        }
        //获取追踪到的脸部信息
        List<Face> faces = mMultiTrack106.getTrackingInfo();
        //绘制追踪点
        points.drawPoints(getPoint(faces));

        if (egl != null)
            egl.swap();
    }

    public void setS(float s) {
        this.s = s;
    }

    public void setH(float h) {
        this.h = h;
    }

    public void setL(float l) {
        this.l = l;
    }

    private float view2openglX(int x, int width) {
        float centerX = width / 2.0f;
        float t = x - centerX;
        return t / centerX;
    }

    private float view2openglY(int y, int height) {
        float centerY = height / 2.0f;
        float s = centerY - y;
        return s / centerY;
    }

    /**
     * 获得脸部106的特征点
     *
     * @param faces
     */
    public float[] getPoint(List<Face> faces) {
        float[] p = new float[]{};
        float[] points = new float[]{};
        for (Face r : faces) {
            points = new float[106 * 2];
            Rect rect = new Rect(CameraUtils.PREVIEW_HEIGHT - r.left, r.top,
                    CameraUtils.PREVIEW_HEIGHT - r.right, r.bottom);
            for (int i = 0; i < 106; i++) {
                int x;
                if (camera.getOrientation() == 270) {
                    x = r.landmarks[i * 2];
                } else {
                    x = CameraUtils.PREVIEW_HEIGHT - r.landmarks[i * 2];
                }
                int y = r.landmarks[i * 2 + 1];
                points[i * 2] = view2openglX(x, CameraUtils.PREVIEW_HEIGHT);
                points[i * 2 + 1] = view2openglY(y, CameraUtils.PREVIEW_WIDTH);
                if (i == 70) {
                    p = new float[8];
                    p[0] = view2openglX(x + 20, CameraUtils.PREVIEW_HEIGHT);
                    p[1] = view2openglY(y - 20, CameraUtils.PREVIEW_WIDTH);
                    p[2] = view2openglX(x - 20, CameraUtils.PREVIEW_HEIGHT);
                    p[3] = view2openglY(y - 20, CameraUtils.PREVIEW_WIDTH);
                    p[4] = view2openglX(x + 20, CameraUtils.PREVIEW_HEIGHT);
                    p[5] = view2openglY(y + 20, CameraUtils.PREVIEW_WIDTH);
                    p[6] = view2openglX(x - 20, CameraUtils.PREVIEW_HEIGHT);
                    p[7] = view2openglY(y + 20, CameraUtils.PREVIEW_WIDTH);
                }
            }
            if (p != null) {
                break;
            }
        }
        return points;
    }
}